const User = require('../models/user')
const Role = require('../models/role')
const decryptByDES = require('../tools/crypto').decryptByDES
const setOutputModel = require('../tools/setOutput')
const setOutput = setOutputModel.setOutput

// 给用户匹配权限
const findRoleForUser = function (types) {
  const findRolePromise = types.map((type) => {
    return Role.findById(type).lean()
  })
  return Promise.all(findRolePromise).then((res) => {
    return Promise.resolve(res)
  }).catch((err) => {
    return Promise.reject(err)
  })
}
const addUser = function(personData) {
  return new Promise((resolve, reject) => {
    
    let obj = {...personData}
    // obj.userName = decryptByDES(obj.userName, 'JOSEPH_CENTER')
    // obj.password = decryptByDES(obj.password, 'JOSEPH_CENTER')
    if (!obj.name) {
      obj.name = obj.userName
    } 
    if (!obj.roleTypes) {
      obj.roleTypes = ['1']
    } 
    findRoleForUser(obj.roleTypes).then((res) => {
      obj.roles = res
      new User(obj).save().then((res) => {
        User.findById(res._id).lean().then((res) => {
          resolve(res)
        }).catch((err) => {
          reject(err)
        })
      }).catch((err) => {
        reject(err)
      })
    }).catch((err) => {
      reject(err)
    }) 
  })
}

class UserController { 
  prefix = '' 
  getPath(name){
    return name ? `/${this.prefix}/${name}` : `/${this.prefix}`
  } 

  addUser(personData) {
    return addUser(personData)
  }

  async add(ctx, next){  
    ctx.verifyParams({
      userName: { type: "string", required: true },
      password: { type: "string", required: true },
      name: { type: 'string', required: false }
    })
    let obj = {...ctx.request.body}
    
    const [err, data] = await to(addUser(obj))
    if(err) return ctx.throw(500, err)
    ctx.response.body = setOutput(data) 
    
  }

  async find(ctx, next) {  
    const {page = 1, pageSize = 20, userName, name, age} = ctx.request.query
    const userNameReg = new RegExp(userName, 'i')
    const nameReg = new RegExp(name, 'i') 

    const total = await User.count({ 
      name: nameReg,
      userName: userNameReg 
    }) // .gte('age', parseInt(age) || 0)

    const list = await User.find({ 
      name: nameReg,
      userName: userNameReg 
    })
    // .gte('age', parseInt(age) || 0)
    .skip((parseInt(page) - 1) * parseInt(pageSize))
    .limit(parseInt(pageSize) || 5).lean() 
    const data = {
      list: list,
      total: total
    }
    ctx.response.body = setOutput(data, 'fetch')
  }

  async findOne(ctx, next) {
    const [err, data] = await to(User.findById(ctx.params.id).lean()) 
    if(err || !data) return ctx.throw(500, err) 
    ctx.response.body = setOutput(data, 'get')
  }

  async delete(ctx, next) {
    await User.deleteOne({ _id: ctx.params.id }) 
    ctx.response.body = {
      data: null,
      code: 0,
      msg: '成功'
    }
  }

  async update(ctx, next){
    ctx.verifyParams({
      id: { type: "string", required: true },
      userName: { type: "string", required: true }
    })
    const obj = {...ctx.request.body}

    delete obj.userName  
    const [err, data] = await to( User.findByIdAndUpdate(obj.id, obj).lean() )
     
    if(err || !data) return ctx.throw(500, err)
    ctx.response.body = setOutput(data, 'update')
  }

  async insertMany(ctx, next) {
    const arr = []
    for (let index = 0; index < 50; index++) {
      const obj = {
        userName: `user_${index}`,
        password: '123456',
        name: `user_${index}`,
        age: 50 + Math.round((Math.random() - 0.5) * 40)
      }
      arr.push(obj)
    }
    const [err, data] = await to( User.insertMany(arr) )
    if(err) return ctx.throw(500, err)
    ctx.response.body = {
      data: data,
      code: 0,
      msg: '成功'
    } 
  }

  async deleteMany(ctx, next) {
    const [err, data] = await to( User.deleteMany() )
    if(err) return ctx.throw(500, err)
    ctx.response.body = {
      data: data,
      code: 0,
      msg: '成功'
    } 
  }
}

module.exports = new UserController()